/**
 * diff组件，用于生成diff
 */

import React from 'react';
import { YunxiaoIcon } from '@alife/devops-ui';
import { parseDiff, Diff, Hunk, markWordEdits } from 'components/diffView';
import intl from '../../locale';
import hljs from 'utils/hl.js';
import './atom-one-light.scss';
import './index.scss';

export default class ProjectTab extends React.Component {
  static propTypes = {};

  static defaultProps = {};

  manualLoadDiff = (diff) => {
    this.props.manualLoadDiff(diff);
  };

  renderHunk = (hunk) => {
    let hunkHeader = null;

    if (hunk.content !== 'STUB') {
      const { diff } = this.props;
      const parsedDiff = parseDiff(diff.diff, { stubHunk: true })[0];
      const oldHunkKey = hunk.content;
      const indexOfHunk = parsedDiff.hunks.findIndex((item) => item.content === oldHunkKey);

      let from;
      let to;

      const prevHunk = parsedDiff.hunks[indexOfHunk - 1];
      const prevHunkEnd = prevHunk ? prevHunk.newStart + prevHunk.newLines : 0;

      const loadMoreLinesBtnGutter = (
        <div
          className="load-more-lines-btn-gutter"
          onClick={() => {
            from = hunk.newStart - 21 > 0 ? hunk.newStart - 21 : 1;
            to = hunk.newStart - 1;
            if (indexOfHunk > 0 && from < prevHunkEnd) {
              from = prevHunkEnd;
            }
            this.props.loadMoreLines({
              from,
              to,
              hunk,
              diff: parsedDiff,
            });
          }}
        >
          <YunxiaoIcon type="more-line" />
        </div>
      );

      const loadMoreLinesBtns = (
        <div className="load-more-lines-btns">
          <a
            className="load-more-lines-btn"
            onClick={() => {
              from = hunk.newStart - 21 > 0 ? hunk.newStart - 21 : 1;
              to = hunk.newStart - 1;
              if (indexOfHunk > 0 && from < prevHunkEnd) {
                from = prevHunkEnd;
              }
              this.props.loadMoreLines({
                from,
                to,
                hunk,
                diff: parsedDiff,
              });
            }}
          >
            <span className="load-more-lines-btn-icon">▲</span>
            {intl.get({
              id: 'code-assets.src.utils.locale.ExpandRows',
              defaultMessage: '展开20行',
            })}
          </a>
          <a
            className="load-more-lines-btn"
            onClick={() => {
              from = prevHunkEnd || 1;
              to = hunk.newStart - 1;
              this.props.loadMoreLines({
                from,
                to,
                hunk,
                diff: parsedDiff,
              });
            }}
          >
            {intl.get({
              id: 'code-assets.src.utils.locale.ExpandAllRows',
              defaultMessage: '展开所有行',
            })}
          </a>
          {indexOfHunk > 0 ? (
            <a
              className="load-more-lines-btn"
              onClick={() => {
                from = prevHunkEnd || 1;
                to = from + 20;
                if (to > hunk.newStart - 1) {
                  to = hunk.newStart - 1;
                }
                this.props.loadMoreLines({
                  from,
                  to,
                  hunk,
                  // hunk: prevHunk,
                  diff: parsedDiff,
                  isAddToEnd: true,
                });
              }}
            >
              <span className="load-more-lines-btn-icon">▼</span>
              {intl.get({
                id: 'code-assets.src.utils.locale.ExpandRows',
                defaultMessage: '展开20行',
              })}
            </a>
          ) : null}
        </div>
      );

      if (
        hunk.newStart !== 1 &&
        hunk.newStart > prevHunkEnd &&
        !diff.deleted_file &&
        !diff.new_file
      ) {
        // hunkHeader = [loadMoreLinesBtnGutter, hunk.content];
        hunkHeader = [loadMoreLinesBtnGutter, loadMoreLinesBtns];
      } else {
        // hunkHeader = [null, hunk.content];
        hunkHeader = null;
      }
    } else {
      // 如果尾部块的末行小于文件总行数，则尾部块可点击加载更多
      const { diff } = this.props;
      const parsedDiff = parseDiff(diff.diff, { stubHunk: true })[0];
      const oldHunkKey = hunk.content;
      const indexOfHunk = parsedDiff.hunks.findIndex((item) => item.content === oldHunkKey);
      const prevHunk = parsedDiff.hunks[indexOfHunk - 1];
      const prevHunkEnd = prevHunk ? prevHunk.newStart + prevHunk.newLines : 0;

      let from;
      let to;

      const loadMoreLinesBtnGutter = (
        <div
          className="load-more-lines-btn-gutter"
          onClick={() => {
            from = diff.lastLineNum || hunk.newStart;
            to = (diff.lastLineNum || hunk.newStart) + 20;
            if (indexOfHunk > 0 && from < prevHunkEnd) {
              from = prevHunkEnd;
            }
            this.props.loadMoreLines({
              from,
              to,
              hunk,
              diff: parsedDiff,
            });
          }}
        >
          <YunxiaoIcon type="more-line" />
        </div>
      );

      const loadMoreLinesBtns = (
        <div className="load-more-lines-btns">
          <a
            className="load-more-lines-btn"
            onClick={() => {
              from = diff.lastLineNum || hunk.newStart;
              to = null; // to不传时，为获取到文件最后一行
              this.props.loadMoreLines({
                from,
                to,
                hunk,
                diff: parsedDiff,
                isLoadEndFinished: true,
              });
            }}
          >
            {intl.get({
              id: 'code-assets.src.utils.locale.ExpandAllRows',
              defaultMessage: '展开所有行',
            })}
          </a>
          {indexOfHunk > 0 ? (
            <a
              className="load-more-lines-btn"
              onClick={() => {
                from = diff.lastLineNum || hunk.newStart;
                to = (diff.lastLineNum || hunk.newStart) + 20;
                if (indexOfHunk > 0 && from < prevHunkEnd) {
                  from = prevHunkEnd;
                }
                this.props.loadMoreLines({
                  from,
                  to,
                  hunk,
                  diff: parsedDiff,
                });
              }}
            >
              <span className="load-more-lines-btn-icon">▼</span>
              {intl.get({
                id: 'code-assets.src.utils.locale.ExpandRows',
                defaultMessage: '展开20行',
              })}
            </a>
          ) : null}
        </div>
      );

      // diff.loadEndFinished 标识文件尾部已加载完，此时不用再展示尾部的块
      if (!diff.loadEndFinished && !diff.deleted_file && !diff.new_file) {
        // hunkHeader = [loadMoreLinesBtnGutter, null];
        hunkHeader = [loadMoreLinesBtnGutter, loadMoreLinesBtns];
      } else {
        hunkHeader = null;
      }
    }

    return <Hunk key={hunk.content} hunk={hunk} header={hunkHeader} />;
  };

  render() {
    const { diff, viewType } = this.props;
    const parseDiffArr = parseDiff(diff.diff, { stubHunk: true });

    // $WAITING_FOR_CLICK_BIG_SIZE$标识了文件体积过大，可能卡死页面
    if (diff.diff === '$WAITING_FOR_CLICK_BIG_SIZE$') {
      return (
        <div className="manual-load-diff-holder" onClick={this.manualLoadDiff.bind(null, diff)}>
          {intl.get({
            id: 'code-assets.src.utils.locale.ThereAreTooManyChanges',
            defaultMessage:
              '此文件或本次改动内容过多，您可以点此手动加载本文件的改动（可能引起页面卡顿，请耐心等待）',
          })}
        </div>
      );
    }

    return (
      <div>
        {parseDiffArr.map(({ hunks, newPath }, i) => (
          <Diff
            key={i}
            viewType={viewType || 'unified'}
            markEdits={markWordEdits({ threshold: 100, markLongDistanceDiff: false })}
            onRenderCode={(td) => {
              // 代码高亮逻辑
              const fileName = newPath.split('/')[newPath.split('/').length - 1];
              let language = '';
              if (fileName.indexOf('.')) {
                language = fileName.split('.')[fileName.split('.').length - 1];
              }
              const originalClass = td.getAttribute('class');
              // 若无后缀，当做js处理，以展示成全黑（若写空或写txt都会被hljs识别为nginx）
              td.setAttribute(
                'class',
                `${originalClass} ${
                  language === 'txt' || language === 'null' || !language ? 'js' : language
                }`,
              );
              hljs.highlightBlock(td);
              return td;
            }}
            genWatermarkimage={this.props.genWatermarkimage}
          >
            {hunks.map(this.renderHunk)}
          </Diff>
        ))}
      </div>
    );
  }
}
